ARCINEX 软件中心：更新方案调研
核验日期：2026-10-23
定位：本次先交付本机可用的软件中心，互联网更新随后接入正式发布环境。

一、推荐方案

采用“产品目录 + 可信更新源 + 成熟安装器”的结构。
目录负责展示五款软件、当前版本、更新说明、兼容要求和下载状态；更新器负责验证、安装和重新启动。支付授权与更新传输分别实现，中心退出后独立工具仍可使用。

本次可以实际完成：扫描 /Applications 和用户 Applications，按 Bundle ID 识别版本；打开已安装软件；比较随中心发布的本地版本目录；选择可信本地安装包并进入安装流程；显式显示线上源是否已配置。没有配置下载服务器时，不能把“已刷新本地目录”写成“已联网检查最新版本”。

正式联网方案：中心定期取得 HTTPS 产品清单，显示更新说明，由用户选择更新。允许后台下载，默认不在用户剪辑时替换应用。SHA-256 用于校验文件完整性；若它与安装包同时来自可变服务器，它不能独立证明发布者身份。生产更新应有固定信任公钥的 Ed25519 签名或 Sparkle 的签名 appcast 与更新包，并校验 Apple 签名身份。

二、GitHub 项目选择

主选 Sparkle：https://github.com/sparkle-project/Sparkle
2026-10-23 查询 GitHub Releases，最新稳定版为 2.10.0，发布于 2026-09-13。
固定版本：https://github.com/sparkle-project/Sparkle/releases/tag/2.10.0
本次已下载官方 SDK，校验官方 GitHub release asset 的 SHA-256，完整保留 framework 符号链接及许可证，编写 CenterSelfUpdate.swift 并通过编译及配置边界测试。未配置线上地址，未进行公网更新安装测试。

值得直接采用的能力：更新签名验证、应用退出后的安装与重启、外部 bundle 更新、下载状态与自定义交互入口。比自己编写具有提权和自更新能力的安装器更合适。中心可保持 ARCINEX 界面，安装环节交给成熟更新框架。

许可证：Sparkle 主体为 MIT。官方完整 LICENSE 还包含 bsdiff/bspatch、sais-lite、Ed25519 和签名验证代码的 BSD/MIT/zlib 类许可。若分发 SDK，保留完整 LICENSE 及版权通知，不只写一句“MIT”。
原文：https://github.com/sparkle-project/Sparkle/blob/2.10.0/LICENSE

三、三类更新要区分

1. 软件中心自身
在中心应用中嵌入 Sparkle，使用 SPUStandardUpdaterController。菜单提供“检查软件中心更新”；下载验证后由框架在退出时安装并重新启动。不能由正在运行的主程序直接覆盖自己的 Contents。

2. 字幕、音频、素材库、视频等独立软件
可以在各软件嵌入 Sparkle，也可以仅由中心统一管理更新。Sparkle 的 SPUUpdater 支持 hostBundle 指向待更新 app，applicationBundle 指向应等待退出、随后重新打开的应用；checkForUpdateInformation 可只取得版本结果，供中心界面展示。适配时仍须保证目标 bundle 的更新源、公钥、版本及签名配置一致。
不必为了“被中心更新”而让每个旧工具都先集成 SDK。没有中心、也没有更新器的旧工具，无法自动发现未来更新，首次仍需用户安装中心或新版工具。应用名称可以更改，识别应以稳定 Bundle ID 和数值构建号为准。

3. 调色助手与 FCP 插件
调色宿主、FxPlug 扩展、效果描述和兼容模板路径属于同一个发行单元。更新时检查 Final Cut Pro 和 Motion 是否仍运行；运行中允许下载，安装等待用户保存并退出。不能为完成更新强制结束剪辑工程。
若只需替换宿主 app，按普通 bundle 更新；若必须安装额外位置文件，使用经过签名及实测的安装包或专用受控安装步骤。Sparkle 支持 pkg，但包安装通常要求管理员授权，没有普通 app 更新的增量包能力，不能作为默认选项滥用。
必须保留效果 UUID、参数编号及旧工程引用路径。否则安装成功也可能让旧时间线出现“缺少效果”。用户预设、LUT、素材索引、模型和项目文件应存于应用支持目录或原有用户目录，更新 app 不覆盖这些数据。

四、最小集成文件

嵌入 SDK 的最小工程改动及当前实施点：

1. 固定并校验 Sparkle 2.10.0 官方发行包或 Swift Package 依赖，不直接跟随不稳定分支。
2. 将完整 Sparkle.framework 嵌入 Contents/Frameworks，保留其 Helpers、XPCServices 等内部结构；不可只复制 dylib。正式构建时按官方要求签名嵌套组件和主应用。
3. 增加 CenterUpdater.swift：保有 updater controller，并连接检查按钮和可用状态。未配置有效 feed 与公钥时不启动更新器，显示“线上更新尚未接入”。
4. Info.plist 至少配置 SUFeedURL、SUPublicEDKey、递增 CFBundleVersion。建议明确关闭默认静默安装；可把自动检查作为用户设置。
5. 对支持的 Sparkle 版本启用 SUVerifyUpdateBeforeExtraction；若使用签名 appcast，再启用 SURequireSignedFeed，并按官方流程签名更新说明。
6. 发版环境保存 generate_keys / sign_update / generate_appcast 工具、私钥备份和发布脚本；私钥不进入 app、源码包、官网或下载清单。generate_keys 默认可使用钥匙串保存私钥。
7. 应用内附上完整 Sparkle LICENSE 和第三方说明。

当前的应用构建已嵌入 SDK；中心缺省无更新源，不启动网络更新。上述正式发布条目不代表已经具备 Developer ID、公证或在线服务器。

本次 SDK 校验记录：ThirdParty/Sparkle/来源与校验.json。官方 Sparkle-2.10.0.tar.xz 为 16,319,840 字节，SHA-256 为 c2bf58aa8387266ac179357b1415d6f2635f044da8be41042af32425dae6da0c。解包前与 GitHub 官方 release API digest 比对一致。原框架深度严格签名验证通过，但原件为 ad-hoc、没有 Team ID；这不等于 Developer ID 签名或 Apple 公证。

手动 swiftc 链接：-F ThirdParty/Sparkle -framework Sparkle -Xlinker -rpath -Xlinker @executable_path/../Frameworks。使用 ditto 复制整个 framework 到 app 的 Contents/Frameworks。正式发版须按官方要求重签嵌套 helpers、XPC、framework 和 app，不能只给外层 app 换一个签名。

本地配置测试：research/CenterSelfUpdateTests.swift；结果 research/self-update-test-results.json，15/15 通过。覆盖官方主机、allowlist、HTTPS、端口、伪造域名、凭据、fragment、文件/相对 URL 以及无源行为。这些测试没有下载或安装真实软件更新。

现有 ReleaseTool 使用 CryptoKit Ed25519，32 字节公钥的 base64 可作为 SUPublicEDKey。它保存的私钥文件为 32 字节 raw seed；Sparkle sign_update --ed-key-file 读取的是 base64 seed 文本，应在受控发布步骤中转换，不直接传入 raw 私钥文件。转换文件同样属于秘密，不能打进安装包。

五、发布目录与开发者日常操作

建议网站与中心共享一个产品目录，产品 ID 稳定，稳定版与测试版分开。每个发行记录包括产品 ID、Bundle ID、显示版本、递增构建号、系统/芯片要求、更新说明、下载地址、字节数、SHA-256、签名、发布日期和安装方式。下载地址不得让服务端清单任意执行 shell 命令或写入任意路径。

建议托管结构：
https://自有域名/catalog/stable.json
https://自有域名/updates/center/appcast.xml
https://自有域名/updates/各产品/appcast.xml
https://下载域名/releases/产品/版本/安装包

发版顺序：构建与回归测试 → Developer ID 签名 → Apple 公证及 stapling → 安装实测 → 生成更新包签名与版本清单 → 先上传不可变版本包 → 最后原子替换清单。保留上一版完整安装包。首次可只发布完整包，流量成为问题时再启用增量更新。

中心界面中的流程：发现新版本 → 查看更新说明 → 下载 → 验证 → 等待相关软件退出 → 安装 → 读取实际安装版本。失败显示具体原因并保留原版；不能仅凭下载结束就标记更新成功。降级不自动进行；配置迁移要保持向后兼容或提供实际可恢复备份。

资源与程序分开：LUT/风格、语音模型等独立版本化，不必每次重装整个软件。已用于工程的资源应保留快照，不让资源库更新改变旧片段画面。

六、当前边界与上线前必须补齐的条件

本地版本检测和本地安装并不等于已部署互联网自动更新。当前应根据真实配置显示状态，不用假下载、假账号、假授权或假更新数量。
公开分发前需要自有域名或稳定 HTTPS 地址、安装包对象存储、Developer ID Application（pkg 另需 Installer）及公证流程、固定的更新签名公钥、私钥备份、至少两台机器的真实升级验证。支付与授权服务以后独立接入，许可校验不进入 FCP 逐帧渲染路径。

官方依据

[1] Sparkle 基本集成与发布签名
https://sparkle-project.org/documentation/
https://sparkle-project.org/documentation/publishing/

[2] SwiftUI / Cocoa 的程序化集成
https://sparkle-project.org/documentation/programmatic-setup/

[3] 外部 Bundle、等待退出和版本探测 API
https://sparkle-project.org/documentation/api-reference/Classes/SPUUpdater.html

[4] Info.plist 配置、自动检查/安装及签名 feed
https://sparkle-project.org/documentation/customization/

[5] pkg 更新限制
https://sparkle-project.org/documentation/package-updates/

[6] Apple Developer ID 与公证
https://developer.apple.com/developer-id/
https://developer.apple.com/documentation/security/notarizing-macos-software-before-distribution

[7] 官方源码与完整许可证
https://github.com/sparkle-project/Sparkle
https://github.com/sparkle-project/Sparkle/blob/2.10.0/LICENSE

参考现有本机规划：
outputs/ARCINEX_软件中心与发布规划_2026-10-22/ARCINEX_商业发布与迭代规划.txt
